package redigopack

import (
	"encoding/json"
	"errors"
	"github.com/gomodule/redigo/redis"
)

type stringRds struct {
	*RedisPool
}

// 设置值
func (s *stringRds) Set(key string, value interface{}, expire ...int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	if len(expire) == 0 {
		return getReply(c.Do("set", kname, value))
	}
	return getReply(c.Do("set", kname, value, "ex", expire[0]))
}

// 获取值
func (s *stringRds) Get(key string) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("get", kname))
}

// 获取JSON数据，并解析
func (s *stringRds) GetJSON(key string, v interface{}) error {
	kname := GetRedisClient().GetPrefixKey(key)
	data, err := s.Get(kname).Bytes()
	if err != nil {
		if errors.Is(err, redis.ErrNil) {
			return nil
		}
		return err
	}

	err = json.Unmarshal(data, v)
	if err != nil {
		return err
	}

	return nil
}

// 将值序列化为JSON，并设置
func (s *stringRds) SetJSON(key string, value interface{}, expire int64) error {
	data, err := json.Marshal(value)
	if err != nil {
		return err
	}
	kname := GetRedisClient().GetPrefixKey(key)
	err = s.Set(kname, data, expire).error
	if err != nil {
		return err
	}

	return nil
}

// key不存在是在设置值
func (s *stringRds) SetNX(key string, value interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("setnx", kname, value))
}

// 	设置并返回旧值
func (s *stringRds) GetSet(key string, value interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("getset", kname, value))
}

// 	设置key并指定生存时间
func (s *stringRds) SetEX(key string, value interface{}, seconds int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("setex", kname, seconds, value))
}

// 	设置key值并指定生存时间(毫秒)
func (s *stringRds) PSetEX(key string, value interface{}, milliseconds int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("psetex", kname, milliseconds, value))
}

// 设置子字符串
func (s *stringRds) SetRange(key string, value interface{}, offset int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("setrange", kname, offset, value))
}

// 	获取子字符串
func (s *stringRds) GetRange(key string, start, end int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("getrange", kname, start, end))
}

// 设置多个值
func (s *stringRds) MSet(kv map[string]interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kv2 := GetRedisClient().MPreName(kv)
	return getReply(c.Do("mset", redis.Args{}.AddFlat(kv2)))
}

// key不存在时设置多个值
func (s *stringRds) MSetNx(kv map[string]interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kv2 := GetRedisClient().MPreName(kv)
	return getReply(c.Do("msetnx", redis.Args{}.AddFlat(kv2)))
}

// 返回多个key的值
func (s *stringRds) MGet(keys []string) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	keysPre := GetRedisClient().SlicePreName(keys)
	return getReply(c.Do("mget", redis.Args{}.AddFlat(keysPre)...))
}

// 自增
func (s *stringRds) Incr(key string) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("incr", kname))
}

// 增加指定值
func (s *stringRds) IncrBy(key string, increment int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("incrby", kname, increment))
}

// 增加一个浮点值
func (s *stringRds) IncrByFloat(key string, increment float64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("incrbyfloat", kname, increment))
}

// 自减
func (s *stringRds) Decr(key string) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("decr", kname))
}

// 自减指定值
func (s *stringRds) DecrBy(key string, increment int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("decrby", kname, increment))
}

// setnxex
func (s *stringRds) SetNXEX(key string, value interface{}, expire int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("set", kname, value, "ex", expire, "nx"))
}

//delete
func (s *stringRds) Delete(key string) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("DEL", kname))
}

//expire
func (s *stringRds) Expire(key string, expire int64) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("EXPIRE", kname, expire))
}

//bf.add
func (s *stringRds) BfAdd(key string, value interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("BF.ADD", kname, value))
}

//bf.reserve
func (s *stringRds) BfReserve(key string, errorRate float32, capacity int) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("BF.RESERVE", kname, errorRate, capacity))
}

//bf.exists
func (s *stringRds) BfExists(key string, value interface{}) *Reply {
	c := s.ConnPool.Get()
	defer c.Close()
	kname := GetRedisClient().GetPrefixKey(key)
	return getReply(c.Do("BF.MEXISTS", kname, value))
}
